import { Component, ViewChild } from '@angular/core';
import { ICellEditorAngularComp } from '@ag-grid-community/angular';
import { Subject } from 'rxjs/internal/Subject';
import { deepClone, getO, getText, getValueUsingField, missing, replaceAll, type } from '../../../utils/utils';
import { of } from 'rxjs/internal/observable/of';
import { catchError, debounceTime, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '@core/services/http/api.service';
import { ExpressionService } from '@core/services/expression/ExpressionService';
import { SearchService } from '@core/services/search.service';
import { NgSelectComponent } from '@shared/apes/ng-select';

@Component({
  selector: 'apes-cell-tag-select',
  template: `
    <ng-select
      [items]="itemsData"
      #select
      style="height:100%"
      [ngStyle]="{'width': params.column.actualWidth+'px' }"
      class="apes-ng-select"
      [disabled]="getDisabled()"
      [placeholder]="placeholder()"
      (change)="onBackFillData($event)"
      [(ngModel)]="inputValue"
      [multiple]="multiple"
      (keydown)="onKeyDown($event)"
      [addTag]="addTag"
      [selectOnTab]="selectOnTab"
      [isOpen]="isOpen">
      <ng-template ng-label-tmp let-item="item" let-clear="clear">
        <span class="ng-value-label">{{formatter(item, getValueFormatter())}}</span>
        <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
      </ng-template>
      <ng-template ng-option-tmp let-item="item">
        {{formatter(item, getDownFormatter())}}
      </ng-template>
    </ng-select>
  `,
  styles: [],
})
export class EditorTagSelectComponent implements ICellEditorAngularComp {

  inputValue: any;
  params: any;
  apesConfig: any;
  ctx: any;
  options = [];

  data: any;

  multiple = true;
  width = 0;
  isLoading = false;
  contractLoading = false;
  itemsData: any;

  selectOnTab: boolean = true;
  isOpen: boolean = false;
  addTag: boolean = true;

  @ViewChild(NgSelectComponent, { static: true })
  private select: NgSelectComponent;

  constructor(private apiService: ApiService, private expressionService: ExpressionService, protected searchService: SearchService) {
  }

  agInit(params: any): void {
    this.params = params;
    this.inputValue = params.value;
    this.ctx = params.context;
    this.apesConfig = this.extend(params);
    this.apesConfig = { ...this.apesConfig, ...params['column']['colDef'] };

    this.width = this.params.width;

    if (this.params.hasOwnProperty('colDef')) {
      this.data = this.params.data;
    } else {
      this.data = this.params.node.data;
    }
  }

  extend(data: any) {
    let result = {};
    for (let key in data) {
      let value = data[key];
      if (key === 'context') {
        result['ctx'] = value;
      } else {
        result[key] = value;
      }
    }
    return result;
  }

  ngAfterViewInit() {
    setTimeout(() => {
      this.select.focus();
    }, 500);
  }

  isPopup(): boolean {
    this.select.open();
    return true;
  }

  onBackFillData(params: any) {
    this.params.value = params;
  }

  getValue(): any {
    let result;
    if (this.inputValue == null || this.inputValue == undefined) {
      result = null;
      this.params.value = null;
    } else {
      result = this.inputValue;
      this.params.value = this.inputValue;
    }
    return result;
  }

  onKeyDown(event): void {
    let key = event.which || event.keyCode;
    if (key === 13) {
      this.preventDefaultAndPropagation(event);
      setTimeout(() => {
        this.select.focus();
      }, 500);
    }
  }

  private preventDefaultAndPropagation(event) {
    event.preventDefault();
    event.stopPropagation();
  }

  getDisabled() {
    return this.apesConfig.disabled || false;
  }

  placeholder() {
    return this.apesConfig.placeholder || '';
  }

  getValueFormatter(): string {
    return this.apesConfig.valueFormatter || 'value';
  }

  getDownFormatter(): string {
    return this.apesConfig.downFormatter || '\'[ \' + value.id + \' ]\' + \' \' + value.name';
  }


  formatter(value: any, expression: string) {
    return this.expressionService.evaluate(expression, {
      context: this.params.context,
      model: this.params.context,
      value: value,
    });
  }
}
